/**
 * 
 * AxLib - JsBox
 * 
 * Author: WaveF
 * QQ: 298010937
 * 
 **/

 ;(function(){

  let axlibPath = getDeploy({ gval: 'AxLib', defaultUrl: 'https://ax.minicg.com/axlib-v3.min.js' });
  let axloaderPath = getDeploy({ gval: 'AxLoader', defaultUrl: 'https://ax.minicg.com/axyepnope.min.js' });

  main();

  function main() {
    if (window.AxJsBox) return;
    window.AxJsBox = { name: 'axjsbox', version: '2.2.0', elements: [] };

    // 添加一个快速获取和设置id的方法
    $.fn.id = function () {
      if (arguments.length == 0) {
        return this.attr('id');
      } else if (arguments.length == 1) {
        this.attr('id', arguments[0]);
      }
    };

    if (!window.yepnope) {
      getAxLoader(inited);
    } else {
      inited();
    }
  }

  function inited() {
    let $jsboxes = $('div[class*="ax-jsbox"]');
    let repeaterIds = [];
    $.each($jsboxes, (idx, item) => { repeaterIds.push($(item).parent().parent().id()); });
    repeaterIds = [...new Set(repeaterIds)];

    $.each(repeaterIds, (idx, item) => {
      let $rep = $('#'+item);
      let repId = $rep.id();
      let rep = $axure(`#${repId}`);
      let $wrapper = $rep.parent();
      let $jsbox = $rep.children('div').eq(0).children('div[class*=ax-jsbox]');
      let jsboxId = $jsbox.id();
      let $textArea = $jsbox.find('textarea');
      let $textAreas = $rep.find('textarea');
      let textAreaId = $textArea.id();
      let $shape = $jsbox.children(`#${jsboxId}_div`);
      let shapeId = $shape.id();
      let js = formatCode($textArea.val());

      let $view = cloneNode($rep);
      let viewId = $view.id();
      $view.insertAfter($rep);

      let panelRawData = rep.getRepeaterDataOnce({format:'default'});
      let extraRawData = rep.getRepeaterDataDiff({format:'default'});
      // extraRawData.splice(0, panelRawData.length);

      let filesInExtra = getFileListFromExtraData(extraRawData) || [], filesInTextarea = getFileListFromTextArea($textArea) || [];
      let files = filesInExtra.concat(filesInTextarea);
      files = [...new Set(files)];

      $rep.hide();
      addLoadingSvg($view);

      let formatInlineFunction = function (func) {
        return func.toString().replace(/VIEW_ID/g, viewId).replace(/REP_ID/g, repId).replace(/JSBOX_ID/g, jsboxId).replace(/TEXTAREA_ID/g, textAreaId).replace(/  /g, '').trim();
      }

      let clearAllTextareas = function () {
        $('#REP_ID').children('div').find('div[class*="ax-jsbox"]').children('textarea').html('');
      }

      let getAllTextareas = function () {
        return $('#REP_ID').children('div').find('div[class*="ax-jsbox"]').children('textarea');
      }

      let getTextarea = function () {
        return $axure('#TEXTAREA_ID');
      }

      let getRepeater = function () {
        return $axure('#REP_ID');
      }

      let getView = function () {
        return $axure('#VIEW_ID');
      }

      let runScript = function (jsUrl) {
        $.get(jsUrl, script => eval(script));
      }

      let setText = function (text) {
        $('#TEXTAREA_ID').val(text);
      }

      let emit = function (action, target) {
        target = target || $axure('#JSBOX_ID');
        if (action.toLowerCase() === 'moved') {
          target.moveBy(0,0,{});
        }
        else if (action==='selected') {
          target.selected(true);
        }
        else if (action==='unselected') {
          target.selected(false);
        }
        else if (action==='toggleSelect') {
          target.selected(!target.selected());
        }
      }

      let showView = function (alpha, pointerEvents) {
        alpha = alpha || 1;
        pointerEvents = pointerEvents || true;
        $('#VIEW_ID').show().css({
          'opacity': alpha,
          'pointer-events': pointerEvents ? 'auto' : 'none'
        });
      }

      let hideView = function () {
        $('#VIEW_ID').hide();
      }

      let setViewStyle = function(css) {
        css = css == 'none' ? { 'border': 'none', 'background-color': 'transparent' } : css;
        $('#VIEW_ID').css(css);
      }

      let showLoading = function () {
        setTimeout(()=>{ $('#VIEW_ID').children('.ax-loading').show(); }, 0);
      }

      let hideLoading = function () {
        setTimeout(()=>{ $('#VIEW_ID').children('.ax-loading').fadeOut(); }, 0);
      }

      let appendHTML = function (str, target) {
        target = target || $('#VIEW_ID');
        target.append(str);
      }

      let appendCSS = function (str) {
        $('head').append('<style>' + str + '</style>');
      }

      let getDataOnce = function (format) {
        return $axure('#REP_ID').getRepeaterDataOnce(format);
      }

      let getExtraData = function (format) {
        return $axure('#REP_ID').getRepeaterDataDiff(format);
      }

      let getLatestData = function (format) {
        return $axure('#REP_ID').getRepeaterData(format);
      }

      let deleteData = function (linesCount) {
        $axure('#REP_ID').deleteRepeaterData(linesCount);
        $axure('#REP_ID').refreshRepeater();
      }

      let clearExtraData = function() {
        let _exData = $axure('#REP_ID').getRepeaterDataDiff();
        $axure('#REP_ID').deleteRepeaterData(_exData.length);
        $axure('#REP_ID').refreshRepeater();
      }

      let clearData = function () {
        $axure('#REP_ID').clearRepeaterData();
        $axure('#REP_ID').refreshRepeater();
      }
      
      let getNode = function (el) {
        let _id, _node;
        if (el.$ !== undefined) {
          _id = el.$().attr('id');
          _node = $(`#${_id}`).get(0);
        } else if (el.jquery !== undefined) {
          _id = el.attr('id');
          _node = $(`#${_id}`).get(0);
        } else if (el.tagName !== undefined) {
          _id = el.id;
          _node = $(`#${_id}`).get(0);
        }
        return _node;
      };
      
      let injectCode = `;let THIS = {
        files: ${`["${files.join('\",\"')}"]`},
        vid: '${viewId}',
        view: $axure('#${viewId}'),
        $view: $axure('#${viewId}').$(),
        rid: '${repId}',
        repeater: $axure('#${repId}'),
        $repeater: $('#${repId}'),
        textarea: $axure('#${textAreaId}'),
        $textarea: $('#${textAreaId}'),
        $textareas: $('#${repId}').find('textarea'),
        jsbox: $axure('#${jsboxId}'),
        $jsbox: $axure('#${jsboxId}').$(),
        shape: $axure('#${shapeId}'),
        $shape: $axure('#${shapeId}').$(),
        size: { width:${ $jsbox.width() }, height:${ $jsbox.height() } },
        position: { x:${ $jsbox.position().left }, y:${ $jsbox.position().top } },
        clearAllTextareas: ${formatInlineFunction(clearAllTextareas)},
        getAllTextareas: ${formatInlineFunction(getAllTextareas)},
        getTextarea: ${formatInlineFunction(getTextarea)},
        getRepeater: ${formatInlineFunction(getRepeater)},
        getView: ${formatInlineFunction(getView)},
        setText: ${formatInlineFunction(setText)},
        emit: ${formatInlineFunction(emit)},
        getData: ${formatInlineFunction(getDataOnce)},
        getDataOnce: ${formatInlineFunction(getDataOnce)},
        getExtraData: ${formatInlineFunction(getExtraData)},
        getLatestData: ${formatInlineFunction(getLatestData)},
        deleteData: ${formatInlineFunction(deleteData)},
        clearExtraData: ${formatInlineFunction(clearExtraData)},
        clearData: ${formatInlineFunction(clearData)},
        appendHTML: ${formatInlineFunction(appendHTML)},
        appendCSS: ${formatInlineFunction(appendCSS)},
        showView: ${formatInlineFunction(showView)},
        hideView: ${formatInlineFunction(hideView)},
        setViewStyle: ${formatInlineFunction(setViewStyle)},
        showLoading: ${formatInlineFunction(showLoading)},
        hideLoading: ${formatInlineFunction(hideLoading)},
        runScript: ${formatInlineFunction(runScript)},
        getNode: ${formatInlineFunction(getNode)}
      };`;
      injectCode = injectCode.replace(/  /g, '').replace(/\n/g, '');
      injectCode = '/* inject begin */\n' + injectCode + '\n/* inject end */\n\n';
      js = injectCode + js;
      js = `(function(){\n${js}\n}());`;
      
      if (files.length === 0) {
        finalAppend($view, js);
      } else {
        yepnope({
          load: files,
          complete: ()=>{
            finalAppend($view, js);
          }
        });
      }
    });
  }

  function finalAppend(container, js) {
    container.append(`<script class="jsbox-script" type="text/javascript">${js}</script>`);
    container.find('.ax-loading').hide();
  }

  function getAxLoader(callback) {
    $.getScript(axloaderPath, ()=>{
      yepnope({
        test: window.axlib,
        nope: axlibPath,
        complete: callback
      });
    });
  }

  function getHostPath() {
      let path = window.location.href;
      let arr = path.split('/');
      arr.pop();
      path = arr.join('/');
      return path;
  }

  function getDeploy(params) {
      let { gval, defaultUrl } = params;
      let deploy = '';
      $axure.internal($ax=>{deploy=$ax.globalVariableProvider.getVariableValue(gval)});
      if (deploy === '') { deploy = defaultUrl; }
      if (deploy.indexOf('{host}')>-1) { deploy = deploy.replace('{host}', getHostPath()); }
      return deploy;
  }

  function formatCode(code) {
      // return code.replace(/ /gi, '').replace(/  +/g, ' ').replace(/\s\s+/g, ' ');
      return code.replace(/ /gi, '').replace(/  +/g, ' ').replace(/\n +/g, '\n').replace(/\n\n+/g, '\n');
  }
  
  function addLoadingSvg(target, options) {
      options = options || { color:'#D1D5DB', opacity:0.2, scale:1.2, delay:0, dur:1, blending:'difference' };

      let svg = `
        <svg xmlns="http://www.w3.org/2000/svg" width="38" height="38" viewBox="0 0 38 38" stroke="${options.color}" style="transform:scale(${options.scale});">
          <g fill="none" fill-rule="evenodd">
            <g transform="translate(1 1)" stroke-width="2">
              <circle stroke-opacity="${options.opacity}" cx="18" cy="18" r="18"/>
              <path d="M36 18c0-9.94-8.06-18-18-18">
                <animateTransform attributeName="transform" type="rotate" from="0 18 18" to="360 18 18" dur="${options.dur}s" repeatCount="indefinite"/>
              </path>
            </g>
          </g>
        </svg>
      `;

      $('head').append(`
        <style>
          html, body { height: 100%; }
          .ax-loading { position: absolute; top: 0; left: 0; width: 100%; height: 100%; background: transparent; z-index: 9999; mix-blend-mode:${options.blending}; pointer-events:none; transform: scale(.5); }
          .ax-loading-svg { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); }
        </style>
      `);
      $(target).append(`<div class="ax-loading"><div class="ax-loading-svg">${svg}</div></div>`);

      return svg;
  }

  function getFileListFromExtraData(data) {
    let temp = $axure.formatRepeaterData(data, { format: 'row' });
    temp = Object.keys(temp);
    // 如果每一项都以 http 开头，那就是文件列表
    return temp.filter(value => value.substr(0, 4) == 'http');
  }

  function getFileListFromTextArea($el) {
    let result = [];
    let lines = $el.val().split('\n');
    lines.forEach(line => {
      let prefix = line.substr(0, 13);
      let pattern = '//import http';
      if (prefix === pattern) {
        result.push(line.replace(pattern, 'http'));
      }
    });
    return result;
  }

  function cloneNode($node) {
    let $clone = $node.clone();
    $clone.children().remove();
    $clone.data('label', '');
    $clone.removeClass('ax_default');
    $clone.addClass($clone.id() + '_clone');
    $clone.id($clone.id() + '_jsbox_view');
    $clone.css({
      'display': 'flex',
      'position': $node.css('position'),
      'left': $node.css('left'),
      'top': $node.css('top'),
      'width': $node.css('width'),
      'height': $node.css('height'),
      'text-align': 'left',
      'border-radius': $node.css('border-radius')
    });
    return $clone;
  }

}());